//using System;
//using System.Collections.Generic;
//using System.Data;
//using Adoor.Object.Domain;
//using Adoor.Relational;
//using Adoor.Relational.RelationalSource;
//using Adoor.Relational.SqlDriver;
//using Adoor.Data;
//using Adoor.Object;
//using Adoor.Object.Query;
//using Adoor.Object.Entity;
//using Adoor.Object.Disconnected;
//using Adoor.Object.Relational;

//namespace Adoor
//{
//    public class ObjectContext : IDisposable
//    {
//        public ObjectContext(string contextName, Adoor.Object.Disconnected.ObjectContext AdoorContext)
//        {
//            this.m_ContextName = contextName;
//            this.AdoorContext = AdoorContext;
//            contextId = Guid.NewGuid();
//        }

//        private Adoor.Object.Disconnected.ObjectContext AdoorContext;

//        public Adoor.Object.Disconnected.ObjectContext AdoorContext
//        {
//            get
//            {
//                return AdoorContext;
//            }
//        }

//        public static void Initialize(Adoor.Relational.NamedConnection namedConnection, bool webApplication)
//        {
//            if (webApplication)
//                Initialize(new Adoor.Web.WebContextStorage(),
//                    namedConnection);
//            else
//                Initialize(new Adoor.Application.ApplicationContextStorage(),
//                    namedConnection);
//        }

//        public bool IsDirty
//        {
//            get
//            {
//                System.Data.DataSet ds = ((DataSetObjectStorage)Current.AdoorContext.LocalStorage).DataSet;
//                return ds.HasChanges();
//            }
//        }

//        public static void Initialize(IAdoorContextStorage storage, Adoor.Relational.NamedConnection namedConnection)
//        {
//            if (Adoor.Object.Disconnected.ObjectContext.ContextStorage == null)
//                Adoor.Object.Disconnected.ObjectContext.ContextStorage = storage;

//            if (namedConnection != null)
//            {
//                storage.DataSourceBuilderType = namedConnection.DataSourceBuilderType;
//                storage.ConnectionString = namedConnection.ConnectionString;
//            }
//        }

//        private int cntUpdateInProgress = 0;

//        public int CountUpdateInProgress
//        {
//            get { return cntUpdateInProgress; }
//        }

//        private ObjectContext()
//        { }


//        public static IAdoorContextStorage ContextStorage
//        {
//            get { return (IAdoorContextStorage)Adoor.Object.Disconnected.ObjectContext.ContextStorage; }
//            set { Adoor.Object.Disconnected.ObjectContext.ContextStorage = value; }
//        }

//        //private static Adoor.ObjectContext current;
//        public static System.Collections.Stack TransactionStack
//        {
//            get
//            {
//                if (ContextStorage == null)
//                {
//                    return new Stack();
//                }
//                return ContextStorage.ContextStack;
//            }
//        }

//        private const string rootContextName = "Root Context";
//        private static void ensureRootContext()
//        {
//            if (TransactionStack.Count == 0)
//            {
//                DataSetObjectStorage localStorage = new DataSetObjectStorage();
//                localStorage.RootDomain = "Root";
//                localStorage.DataSet.DataSetName = rootContextName;

//                Adoor.Object.Disconnected.ObjectContext context = new Adoor.Object.Disconnected.ObjectContext(new RemoteSourceProvider(ContextStorage, localStorage.RootDomain));

//                Relational.NamedConnection nc = new Adoor.Relational.NamedConnection();
//                nc.DataSourceBuilderType = ContextStorage.DataSourceBuilderType;
//                nc.ConnectionString = ContextStorage.ConnectionString;

//                RelationalObjectSource relationalSource = new RelationalObjectSource();
//                relationalSource.RelationalSource = nc.DataSourceBuilder.CreateRelationalSource();
//                relationalSource.RootDomain = localStorage.RootDomain;
//                context.LocalStorage = localStorage;

//                TransactionStack.Push(new ObjectContext(rootContextName, context));
//                OnBeginTransactionContext();
//            }
//        }

//        private string m_ContextName;
//        public String ContextName
//        {
//            get { return m_ContextName; }
//        }

//        private Guid contextId;
//        public Guid ContextId
//        {
//            get { return contextId; }
//        }

//        public bool Disconnected
//        {
//            get { return AdoorContext.Disconnected; }
//            set { /*AdoorContext.Disconnected = value;*/ }
//        }

//        /// <summary>
//        /// Access to current context.
//        /// </summary>
//        public static Adoor.ObjectContext Current
//        {
//            get
//            {
//                System.Threading.Monitor.Enter(ContextStorage);
//                try
//                {
//                    ensureRootContext();
//                    ObjectContext container = (ObjectContext)TransactionStack.Peek();
//                    return container;
//                }
//                finally
//                {
//                    System.Threading.Monitor.Exit(ContextStorage);
//                }
//            }
//        }

//        public Adoor.Object.Relational.RelationalObjectSource RemoteSource
//        {
//            get
//            {
//                return ((RemoteSourceProvider)this.AdoorContext.RemoteSourceProvider).ObjectSource;
//            }
//        }

//        public IObjectStorage LocalStorage
//        {
//            get
//            {
//                return AdoorContext.LocalStorage;
//            }
//        }

//        public static event EventHandler BeginTransactionContext;

//        protected static void OnBeginTransactionContext()
//        {
//            if (BeginTransactionContext != null)
//                BeginTransactionContext(null, EventArgs.Empty);
//        }

//        /// <summary>
//        /// Clear session context : Use this to change session.
//        /// </summary>
//        public static void ResetRootContext()
//        {
//            TransactionStack.Clear();
//        }

//        #region simule un transaction manager

//        /// <summary>
//        /// simulate a transaction start by creating a new current context.
//        /// </summary>
//        /// <param name="aTransactionName"> new context name </param>
//        /// <param name="mode">data replication mode</param>
//        public static Guid BeginTransaction(String aTransactionName, CloneMode mode)
//        {
//            System.Threading.Monitor.Enter(ContextStorage);
//            try
//            {
//                ObjectContext newContext = CreateSubcontext(aTransactionName, mode);
//                TransactionStack.Push(newContext);
//                OnBeginTransactionContext();
//                return newContext.ContextId;
//            }
//            finally
//            {
//                System.Threading.Monitor.Exit(ContextStorage);
//            }
//        }

//        /// <summary>
//        /// Simulate a transaction commit by merging the data with in parent context
//        /// </summary>
//        [Obsolete("Use CommitTransaction(bool pop", true)]
//        public static void CommitTransaction()
//        {
//            CommitTransaction(true);
//        }

//        /// <summary>
//        /// Simulate a transaction commit by merging the data with in parent context
//        /// </summary>
//        public static void CommitTransaction(bool pop)
//        {
//            System.Threading.Monitor.Enter(ContextStorage);
//            try
//            {
//                ObjectContext context = (ObjectContext)TransactionStack.Pop();
//                context.mergeToDsDeleted();

//                MergeContext(context, Current);

//                if (!pop)
//                {
//                    TransactionStack.Push(context);
//                }
//            }
//            finally
//            {
//                System.Threading.Monitor.Exit(ContextStorage);
//            }
//        }

//        public void ClearContext()
//        {
//            System.Data.DataSet dsSource = ((DataSetObjectStorage)this.AdoorContext.LocalStorage).DataSet;
//            dsSource.Clear();
//        }

//        public static void MergeContext(ObjectContext contextSource, ObjectContext contextDest)
//        {
//            while (contextSource.cntUpdateInProgress != 0
//                || contextDest.cntUpdateInProgress != 0)
//            {
//                System.Diagnostics.Trace.WriteLine(
//                    "update in progress waiting before merging ctxt contextSource.cntUpdateInProgress "
//                    + contextSource.cntUpdateInProgress
//                    + " contextDest.cntUpdateInProgress " + contextDest.cntUpdateInProgress);
//                System.Threading.Thread.Sleep(100);
//            }

//            System.Data.DataSet dsSource = ((DataSetObjectStorage)contextSource.AdoorContext.LocalStorage).DataSet;
//            System.Data.DataSet dsDest = ((DataSetObjectStorage)contextDest.AdoorContext.LocalStorage).DataSet;

//            clearExtendedProperties(dsSource);
//            mergeDataSet(dsSource, dsDest, contextSource.dsBeforeRollBack);
//        }

//        private static void mergeDataSet(System.Data.DataSet source, System.Data.DataSet dest, System.Data.DataSet sourceDeleted)
//        {
//            foreach (System.Data.DataTable dtSource in source.Tables)
//            {
//                System.Data.DataTable dtDest = dest.Tables[dtSource.TableName];
//                if (dtDest == null)
//                {
//                    DataTable dt = dtSource.Copy();
//                    dt.TableName = dtSource.TableName;
//                    dest.Tables.Add(dt);
//                }
//                else
//                {
//                    System.Text.StringBuilder sb = new System.Text.StringBuilder();

//                    System.Collections.ArrayList colsToDelete = new System.Collections.ArrayList();
//                    if (dtDest.Columns.Count != dtSource.Columns.Count)
//                    {
//                        foreach (System.Data.DataColumn dc in dtSource.Columns)
//                        {
//                            if (dtDest.Columns[dc.ColumnName] == null)
//                                colsToDelete.Add(dc.Ordinal);
//                        }
//                    }

//                    foreach (System.Data.DataRow dr in dtSource.Rows)
//                    {
//                        sb.Length = 0;
//                        for (int i = 0; i < dtSource.PrimaryKey.Length; i++)
//                        {
//                            System.Data.DataColumn dc = dtSource.PrimaryKey[i];
//                            sb.Append(dc.ColumnName);
//                            sb.Append(" = '");
//                            sb.Append(dr[dc.Ordinal]);
//                            sb.Append("'");
//                            if (i != dtSource.PrimaryKey.Length - 1)
//                                sb.Append(" AND ");
//                        }
//                        System.Data.DataRow[] drsDest = dtDest.Select(sb.ToString());
//                        System.Data.DataRow drDest = null;
//                        System.Diagnostics.Debug.Assert(drsDest.Length <= 1);

//                        if (drsDest.Length == 1)
//                            drDest = drsDest[0];

//                        if (drDest != null && drDest.RowState == System.Data.DataRowState.Modified)
//                            continue;

//                        if (dtDest.Columns.Count == dtSource.Columns.Count)
//                        {
//                            if (drDest == null)
//                            {
//                                if (dr.RowState == System.Data.DataRowState.Added)
//                                    drDest = dtDest.LoadDataRow(dr.ItemArray, false);
//                                else if (dr.RowState == System.Data.DataRowState.Modified)
//                                {
//                                    drDest = dtDest.LoadDataRow(dr.ItemArray, true);
//                                    drDest.ItemArray = dr.ItemArray;
//                                }
//                                else
//                                    drDest = dtDest.LoadDataRow(dr.ItemArray, true);
//                            }
//                            else
//                            {
//                                drDest.ItemArray = dr.ItemArray;
//                                if (dr.RowState == System.Data.DataRowState.Unchanged)
//                                    drDest.AcceptChanges();
//                            }
//                        }
//                        else
//                        {
//                            System.Collections.ArrayList alRow = new System.Collections.ArrayList(dr.ItemArray);
//                            for (int i = colsToDelete.Count - 1; i >= 0; i--)
//                            {
//                                alRow.RemoveAt((int)colsToDelete[i]);
//                            }

//                            if (drDest == null)
//                            {
//                                dtDest.LoadDataRow(alRow.ToArray(), true);
//                            }
//                            else
//                            {
//                                drDest.ItemArray = alRow.ToArray();
//                                if (dr.RowState == System.Data.DataRowState.Unchanged)
//                                    drDest.AcceptChanges();
//                            }
//                        }

//                    }
//                }
//            }

//            sourceDeleted.RejectChanges();
//            foreach (System.Data.DataTable dtDeleted in sourceDeleted.Tables)
//            {
//                System.Text.StringBuilder sb = new System.Text.StringBuilder();
//                System.Data.DataTable dtDest = dest.Tables[dtDeleted.TableName];
//                if (dtDest != null)
//                {
//                    foreach (DataRow dr in dtDeleted.Rows)
//                    {
//                        sb.Length = 0;
//                        for (int i = 0; i < dtDeleted.PrimaryKey.Length; i++)
//                        {
//                            System.Data.DataColumn dc = dtDeleted.PrimaryKey[i];
//                            sb.Append(dc.ColumnName);
//                            sb.Append(" = '");
//                            sb.Append(dr[dc.Ordinal]);
//                            sb.Append("'");
//                            if (i != dtDeleted.PrimaryKey.Length - 1)
//                                sb.Append(" AND ");
//                        }
//                        System.Data.DataRow[] drsDest = dtDest.Select(sb.ToString());
//                        System.Diagnostics.Debug.Assert(drsDest.Length <= 1);

//                        if (drsDest.Length == 1)
//                        {
//                            drsDest[0].Delete();
//                            drsDest[0].AcceptChanges();
//                        }
//                    }
//                }
//            }
//        }

//        private static void clearExtendedProperties(System.Data.DataSet ds)
//        {
//            //ds.ExtendedProperties.Clear();
//            foreach (System.Data.DataTable dt in ds.Tables)
//                dt.ExtendedProperties.Clear();
//        }

//        /// <summary>
//        /// Simulate a rollback by discarding the context and returning to the previous one.
//        /// </summary>
//        public static void RollBackTransaction()
//        {
//            System.Threading.Monitor.Enter(ContextStorage);
//            try
//            {
//                ObjectContext ctxt = (ObjectContext)TransactionStack.Pop();
//                ctxt.ReleaseDispose();
//            }
//            finally
//            {
//                System.Threading.Monitor.Exit(ContextStorage);
//            }
//        }

//        #endregion

//        #region context stack management

//        /// <summary>
//        /// reate a child context from current one.
//        /// </summary>
//        /// <param name="aContextName">Name of the child context</param>
//        /// <param name="mode"> Clone mode</param>
//        /// <returns>a new IObjectContext instance</returns>
//        public static ObjectContext CreateSubcontext(String aContextName, CloneMode mode)
//        {
//            return CreateSubcontext(aContextName, mode, Current);
//        }

//        /// <summary>
//        /// reate a child context from current one.
//        /// </summary>
//        /// <param name="aContextName">Name of the child context</param>
//        /// <param name="mode"> Clone mode</param>
//        /// <returns>a new IObjectContext instance</returns>
//        public static ObjectContext CreateSubcontext(String aContextName, CloneMode mode, ObjectContext source)
//        {
//            System.Threading.Monitor.Enter(ContextStorage);
//            try
//            {
//                IObjectStorage localStorageClone = source.AdoorContext.LocalStorage.Clone(translateCloneMode(mode));

//                Adoor.Object.Disconnected.ObjectContext newAdoorContext = new Adoor.Object.Disconnected.ObjectContext(new RemoteSourceProvider(ContextStorage, localStorageClone.RootDomain));
//                newAdoorContext.Site = source.AdoorContext.Site;
//                newAdoorContext.LocalStorage = localStorageClone;

//                clearExtendedProperties(((DataSetObjectStorage)newAdoorContext.LocalStorage).DataSet);

//                ((DataSetObjectStorage)newAdoorContext.LocalStorage).DataSet.DataSetName = aContextName;

//                ObjectContext ctxt = new ObjectContext(aContextName, newAdoorContext);
//                //Adoor.DAL.Restitution.CurrentContext = context;

//                return ctxt;
//            }
//            finally
//            {
//                System.Threading.Monitor.Exit(ContextStorage);
//            }
//        }

//        /// <summary>
//        /// discard current context and return to previous one.
//        /// </summary>
//        public static void DiscardSubcontext()
//        {
//            System.Threading.Monitor.Enter(ContextStorage);
//            try
//            {
//                if (TransactionStack.Count > 1)
//                    TransactionStack.Pop();
//                else
//                    throw new InvalidOperationException("Discarding the root context is not allowed.");
//            }
//            finally
//            {
//                System.Threading.Monitor.Exit(ContextStorage);
//            }
//        }
//        #endregion

//        #region utils
//        /// <summary>
//        /// hide technical framework enumeration
//        /// </summary>
//        /// <param name="mode">Adoor clone mode</param>
//        /// <returns>technical framework clone mode</returns>
//        private static Adoor.Object.Entity.CloneMode translateCloneMode(CloneMode mode)
//        {
//            switch (mode)
//            {
//                case CloneMode.Empty:
//                    return Adoor.Object.Entity.CloneMode.Empty;
//                case CloneMode.NewData:
//                    return Adoor.Object.Entity.CloneMode.NewData;
//                case CloneMode.NoData:
//                    return Adoor.Object.Entity.CloneMode.NoData;
//                case CloneMode.Full:
//                    return Adoor.Object.Entity.CloneMode.Full;
//                default:
//                    throw new NotSupportedException("Invalid value for CloneMode enum : " + mode.ToString());

//            }
//        }
//        #endregion


//        public DataSet GetDataSet()
//        {
//            return ((DataSetObjectStorage)this.AdoorContext.LocalStorage).DataSet;
//        }

//        public void Fill(DataSet dataset, Type type)
//        {
//            AdoorContext.Fill(dataset, type);
//        }

//        public void Fill(DataSet dataset, string query, IDictionary<string, object> args)
//        {
//            AdoorContext.Fill(dataset, query, args);
//        }

//        public void Fill(DataSet dataset, string query, params object[] args)
//        {
//            AdoorContext.Fill(dataset, query, args);
//        }

//        public void Fill(DataSet dataset, ObjectQuery query, object[] args)
//        {
//            AdoorContext.Fill(dataset, query, args);
//        }

//        public void Fill(DataSet dataset, string tableName, Type type)
//        {
//            AdoorContext.Fill(dataset, tableName, type);
//        }

//        public void Fill(DataSet dataset, string tableName, string query, IDictionary<string, object> args)
//        {
//            AdoorContext.Fill(dataset, tableName, query, args);
//        }

//        public void Fill(DataSet dataset, string tableName, string query, params object[] args)
//        {
//            AdoorContext.Fill(dataset, tableName, query, args);
//        }

//        public void Fill(DataSet dataset, string tableName, ObjectQuery query, object[] args)
//        {
//            AdoorContext.Fill(dataset, tableName, query, args);
//        }

//        public void Fill(DataTable table, Type type)
//        {
//            AdoorContext.Fill(table, type);
//        }

//        public void Fill(DataTable table, string query, IDictionary<string, object> args)
//        {
//            AdoorContext.Fill(table, query, args);
//        }

//        public void Fill(DataTable table, string query, params object[] args)
//        {
//            AdoorContext.Fill(table, query, args);
//        }

//        public void Fill(DataTable table, ObjectQuery query, object[] args)
//        {
//            AdoorContext.Fill(table, query, args);
//        }

//        public Int64 GetCount(Type type)
//        {
//            return AdoorContext.GetCount(type);
//        }

//        public Int64 GetCount(ObjectQuery query, IDictionary<string, object> args)
//        {
//            return AdoorContext.GetCount(query, args);
//        }

//        public Int64 GetCount(ObjectQuery query, object[] args)
//        {
//            return AdoorContext.GetCount(query, args);
//        }

//        public Int64 GetCount(string query, params object[] args)
//        {
//            return AdoorContext.GetCount(query, args);
//        }

//        public IDataReader GetReader(Type type)
//        {
//            return AdoorContext.GetReader(type);
//        }

//        public IDataReader GetReader(ObjectQuery query, IDictionary<string, object> args)
//        {
//            return AdoorContext.GetReader(query, args);
//        }

//        public IDataReader GetReader(ObjectQuery query, object[] args)
//        {
//            return AdoorContext.GetReader(query, args);
//        }

//        public IDataReader GetReader(string query, params object[] args)
//        {
//            return AdoorContext.GetReader(query, args);
//        }

//        public object Find(Type baseType, string oid)
//        {
//            return AdoorContext.Find(baseType, oid);
//        }

//        public object Find(string oid)
//        {
//            if (oid == null || string.Empty.Equals(oid))
//                return null;

//            return AdoorContext.Find(Adoor.Helpers.GetTypeFromOid(oid), oid);
//        }

//        public object Find(EntityData entityData, string oid)
//        {
//            return AdoorContext.Find(entityData, oid);
//        }

//        public ICollection Collect(Type type)
//        {
//            return AdoorContext.Collect(type);
//        }

//        public ICollection Collect(ObjectQuery query, IDictionary<string, object> args)
//        {
//            return AdoorContext.Collect(query, args);
//        }

//        public ICollection Collect(ObjectQuery query, object[] args)
//        {
//            return AdoorContext.Collect(query, args);
//        }

//        public ICollection Collect(string query, params object[] args)
//        {
//            return AdoorContext.Collect(query, args);
//        }

//        private DataSet dsBeforeRollBack = new DataSet();

//        private void mergeToDsDeleted()
//        {
//            System.Data.DataSet dsDeleted = ((DataSetObjectStorage)this.AdoorContext.LocalStorage).DataSet.GetChanges(DataRowState.Deleted);
//            if (dsDeleted != null)
//                dsBeforeRollBack.Merge(dsDeleted, true, MissingSchemaAction.AddWithKey);
//        }

//        public void Update()
//        {
//            updateInternal(null);
//        }

//        public void UpdateSelectedEntities(params Type[] entitypes)
//        {
//            ArrayList al = new ArrayList();
//            foreach (Type t in entitypes)
//            {
//                EntityData ed = ObjectDomain.Current.EntityInfos[t];
//                if (ed == null)
//                    throw new Exception("EntityType " + t.Name + " is not a registered entity ");
//                al.Add(ed);
//            }
//            AdoorContext.UpdateSelectedEntities((EntityData[])al.ToArray(typeof(EntityData)));
//        }

//        public void AsyncUpdate()
//        {
//            AsyncUpdate(null);
//        }

//        public void AsyncUpdate(System.Threading.ThreadStart callBack)
//        {
//            HoldDispose();
//            internalMethodCall mc = new internalMethodCall(updateInternal);
//            mc.BeginInvoke(callBack, new AsyncCallback(endUpdate), mc);
//        }

//        private System.Threading.ThreadStart updateInternal(System.Threading.ThreadStart callBack)
//        {
//            System.Threading.Interlocked.Increment(ref cntUpdateInProgress);
//            System.Diagnostics.Debug.WriteLine("Inc Update in progress" + cntUpdateInProgress + " " + System.Threading.Thread.CurrentThread.GetHashCode());
//            HoldDispose();
//            try
//            {
//                mergeToDsDeleted();
//                AdoorContext.Update();
//                return callBack;
//            }
//            finally
//            {
//                System.Threading.Interlocked.Decrement(ref cntUpdateInProgress);
//                System.Diagnostics.Debug.WriteLine("Dec Update in progress" + cntUpdateInProgress + " " + System.Threading.Thread.CurrentThread.GetHashCode());
//                ReleaseDispose();
//            }
//        }

//        private void endUpdate(IAsyncResult res)
//        {
//            internalMethodCall mc = (internalMethodCall)res.AsyncState;
//            System.Threading.ThreadStart callBack = mc.EndInvoke(res);
//            if (callBack != null)
//                callBack.DynamicInvoke(null);
//            ReleaseDispose();
//        }

//        private delegate System.Threading.ThreadStart internalMethodCall(System.Threading.ThreadStart callBack);

//        public void Preload(Type type)
//        {
//            AdoorContext.Preload(type);
//        }

//        public void Preload(string text, params object[] args)
//        {
//            AdoorContext.Preload(text, args);
//        }

//        public void Preload(ObjectPath path, object[] args)
//        {
//            AdoorContext.Preload(path, args);
//        }

//        public bool CheckIntegrity
//        {
//            get { return AdoorContext.LocalStorage.CheckIntegrity; }
//            set { AdoorContext.LocalStorage.CheckIntegrity = value; }
//        }

//        #region IDisposable Members

//        private int cntDispose = 1;

//        public void HoldDispose()
//        {
//            cntDispose++;
//        }

//        public void ReleaseDispose()
//        {
//            cntDispose--;
//            if (cntDispose == 0)
//            {
//                if (AdoorContext != null)
//                    AdoorContext.Dispose();
//            }
//        }

//        public void Dispose()
//        {
//            ReleaseDispose();
//        }

//        #endregion
//    }
//}
